package com.asen.sys.utils;

import com.asen.sys.domain.DictItem;
import com.asen.sys.enums.CacheTypeEnum;
import com.asen.commons.core.base.enums.DictTypeEnum;
import com.asen.commons.core.base.enums.ValueTypeEnum;
import com.asen.commons.cache.RedisCache;
import com.asen.commons.context.ContextHolder;
import com.asen.commons.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 数据字典工具类
 *
 * @author Gary
 * @version 1.0
 * @date 2018-12-17
 */
public class DictUtils {

    private static final Logger logger = LoggerFactory.getLogger(DictUtils.class);

    /**
     * 获取数据字典标签
     *
     * @param dictType 类型编码
     * @param value    字典数值
     * @return
     * @throws Exception
     */
    public static String getLabel(DictTypeEnum dictType, String value) {
        if (dictType == null || StringUtils.isBlank(value)) {
            return null;
        }

        String label = null;
        try {
            String key = dictType.getValue() + "#DataList";
            RedisCache redisCache = (RedisCache) SpringUtil.getBean("redisCache");
            label = (String) redisCache.getHash(CacheTypeEnum.DICT_DATA.name(), key, value);
            if (label == null) {
                DictItem item = fetchData(dictType, value);
                if (item != null) {
                    cacheUpdate(item);
                    label = item.getLabel();
                } else {
                    cacheNull(dictType.getValue(), value);
                }
            }
        } catch (Exception ex) {
            logger.error("获取dictType:{},value为{}的label失败,错误信息:{}", dictType, value, ex.getCause());
        }
        return label;
    }

    /**
     * 获取数据字典项
     *
     * @param dictType 类型编码
     * @param value
     * @return
     * @throws Exception
     */
    public static DictItem getDictData(DictTypeEnum dictType, String value) {
        if (dictType == null || value == null) {
            return null;
        }

        DictItem item = null;
        try {
            String type = dictType.getValue();
            String key = type + "#DataList";
            RedisCache redisCache = (RedisCache) SpringUtil.getBean("redisCache");
            String label = (String) redisCache.getHash(CacheTypeEnum.DICT_DATA.name(), key, value);
            if (label == null) {
                item = fetchData(dictType, value);
                if (item != null) {
                    cacheUpdate(item);
                } else {
                    cacheNull(type, value);
                }
            } else {
                item = new DictItem();
                item.setType(dictType.getValue());
                item.setValue(value);
                item.setLabel(label);
            }
        } catch (Exception e) {
            logger.error("刷新缓存失败", e);
        }

        return item;
    }

    private static DictItem fetchData(DictTypeEnum dictType, String value) throws Exception {
        String type = dictType.getValue();
        Map json = null;
        // TODO
//        String path = "/inner/sys/dictData/getByValue?type=" + type + "&value=" + value;
//        Map json = RestUtils.get(ServiceNameEnum.SCP_SYS, path, Map.class);
        if (json != null) {
            DictItem dataItem = new DictItem();
            dataItem.setType(type);
            dataItem.setValue(value);
            dataItem.setLabel((String) json.get("label"));
            return dataItem;
        }
        return null;
    }

    public static String[] getDictLabelList(DictTypeEnum dictType) throws Exception {
        List<DictItem> dictItems = getDictList(dictType);
        if (CollectionUtils.isEmpty(dictItems)){
            return null;
        }
        List<String> labels = new ArrayList<>();
        for (DictItem dictItem:dictItems) {
            labels.add(dictItem.getLabel());
        }
        return labels.toArray(new String[0]);
    }

    /**
     * 获取指定类型数据字典列表，不包括已禁用数据
     *
     * @param dictType 类型编码
     * @return
     * @throws Exception
     */
    public static List<DictItem> getDictList(DictTypeEnum dictType) throws Exception {
        List<DictItem> itemList = null;

        try {
            String key = dictType.getValue() + "#DataList";
            String contextKey = CacheTypeEnum.DICT_DATA.name() + "#" + key;
            String json = (String) ContextHolder.get(contextKey);

            if (json == null) {
                // TODO
                json = null;
//                String path = "/inner/sys/dictData/getByType?type=" + dictType.getValue();
//                json = RestUtils.get(ServiceNameEnum.SCP_SYS, path, String.class);
                if (StringUtils.isBlank(json)) {
                    ContextHolder.put(contextKey, "");
                    return null;
                }

                itemList = JsonMapper.json2list(json, DictItem.class);
                if (itemList != null && itemList.size() > 0) {
                    cache(dictType, itemList);
                }
                ContextHolder.put(contextKey, json);
                return itemList;
            }

            if (StringUtils.isBlank(json)) {
                return null;
            }

            itemList = JsonMapper.json2list(json, DictItem.class);
        } catch (Exception e) {
            logger.error("刷新缓存失败", e);
        }

        return itemList;
    }

    /**
     * 获取数据字典类型
     *
     * @param dictType
     * @return
     * @throws Exception
     */
    public static ValueTypeEnum getValueType(DictTypeEnum dictType) throws Exception {
        RedisCache redisCache = (RedisCache) SpringUtil.getBean("redisCache");
        String type = (String) redisCache.get(CacheTypeEnum.DICT_DATA.name(), dictType.getValue() + "#ValueType");
        return EnumUtils.valueOf(ValueTypeEnum.class, type);
    }

    /**
     * 更新缓存
     *
     * @param dictType
     * @param dataList
     * @throws Exception
     */
    public static void cache(DictTypeEnum dictType, List<DictItem> dataList) throws Exception {
        cache(dictType.getValue(), dataList);
    }

    /**
     * 更新缓存
     *
     * @param type
     * @param dataList
     * @throws Exception
     */
    public static void cache(String type, List<DictItem> dataList) throws Exception {
        if (dataList != null && dataList.size() > 0) {
            RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
            redisCache.remove(CacheTypeEnum.DICT_DATA.name(), type + "#ValueType");
            redisCache.remove(CacheTypeEnum.DICT_DATA.name(), type + "#DataList");
            redisCache.put(CacheTypeEnum.DICT_DATA.name(), type + "#ValueType", ValueTypeEnum.TEXT);

            String dataKey = type + "#DataList";
            dataList.forEach(data -> {
                redisCache.putHash(CacheTypeEnum.DICT_DATA.name(), dataKey, data.getValue(), data.getLabel());
            });
        }
    }

    /**
     * 更新缓存
     *
     * @param dictItem
     * @throws Exception
     */
    public static void cacheUpdate(DictItem dictItem) throws Exception {
        if (dictItem != null) {
            RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
            String dataKey = dictItem.getType() + "#DataList";
            redisCache.putHash(CacheTypeEnum.DICT_DATA.name(), dataKey, dictItem.getValue(), dictItem.getLabel());
        }
    }

    /**
     * 缓存删除
     *
     * @param dictType
     * @throws Exception
     */
    public static void cacheRemove(DictTypeEnum dictType) throws Exception {
        if (dictType != null) {
            RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
            redisCache.remove(CacheTypeEnum.DICT_DATA.name(), dictType.getValue() + "#ValueType");
            redisCache.remove(CacheTypeEnum.DICT_DATA.name(), dictType.getValue() + "#DataList");
        }
    }

    /**
     * 缓存删除
     *
     * @param dictItem
     * @throws Exception
     */
    public static void cacheRemove(DictItem dictItem) throws Exception {
        if (dictItem != null) {
            RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
            String dataKey = dictItem.getType() + "#DataList";
            redisCache.removeHash(CacheTypeEnum.DICT_DATA.name(), dataKey, dictItem.getValue());
        }
    }


    /**
     * 初始化缓存
     *
     * @param type
     * @param value
     * @throws Exception
     */
    public static void cacheNull(String type, String value) throws Exception {
        if (StringUtils.isEmpty(type) || StringUtils.isEmpty(value)) {
            return;
        }

        String key = type + "#DataList";
        String hashKey = value;
        RedisCache redisCache = SpringUtil.getBean(RedisCache.class);
        redisCache.putHash(CacheTypeEnum.DICT_DATA.name(), key, hashKey, "");
    }
}
